import { useState, useEffect, CSSProperties } from "react";
import { Form, InputNumber, Select, Input } from "antd";
import { useComponentsStore } from "../../stores/components";
import { ComponentConfig, ComponentSetter, useComponentConfigStore } from "../../stores/component-config";
import { CssEditor } from "./CssEditor";
import { debounce } from "lodash-es";
import styleToObject from "style-to-object";

export const ComponentStyle = () => {
    const [form] = Form.useForm();

    const { curComponentId, curComponent, updateComponentStyles } = useComponentsStore();
    const { componentConfig } = useComponentConfigStore();

    if(!curComponent || !curComponentId) return null;

    const [css, setCss] = useState<string>(`.com{\n\n}`);

    const renderFormElement = ({ options, type }: ComponentSetter): React.ReactNode => {
        if(type === 'select') {
            return <Select options={options} />
        }else if(type === 'input') {
            return <Input />
        }else if(type === 'inputNumber') {
            return <InputNumber />
        }else {
            return null
        }
    }

    const valuesChange = (changeValues: CSSProperties)=>{
        if(curComponentId) {
            updateComponentStyles(curComponentId, changeValues);
        }
    }

    // 引入lodash 防抖函数
    const handleEditorChange = debounce((value)=>{
        setCss(value);
        
        let css: Record<string, any> = {};
        // store中是对象类型的样式，所以我们使用style-to-object库将字符串格式的style样式转化为对象类型
        // 这个库只能转化这样格式的样式 parse('color: #C0FFEE; background: #BADA55;');
        // 所以我们首先要先将可能出现的注释，以及类名去掉
        try {
            const cssStr = value.replace(/\/\*.*\*\//, "") // 去掉 /* */注释
                .replace(/(\.?[^{]+{)/, '') // 去掉 .com {
                .replace('}', ''); // 去掉 }
            styleToObject(cssStr, (name, value) => {
                // style-to-object库默认处理完是短线连接的，react中样式都是驼峰的，我们需要转化一下
                css[name.replace(/-\w/, (item)=> item.toUpperCase().replace('-',''))] = value;
            });
            
            updateComponentStyles(curComponentId, {...form.getFieldsValue(), ...css}, true);     
        } catch (error) {}
    }, 500)

    const toCssStr = (css: Record<string, any>): string => {
        let str = `.com {\n`;
        for(let key in css) {
            let value = css[key];
            if(!value) continue;
            if(['width', 'height'].includes(key) && !value.toString().endsWith('px')) {
                value += 'px';
            }

            str+=`\t${key}: ${value};\n`;
        }
        str+=`}`;
        return str;
    }

    useEffect(()=>{
        form.resetFields();
        const data = form.getFieldsValue();
        form.setFieldsValue({...data, ...curComponent?.styles});
        setCss(toCssStr(curComponent?.styles!))
    }, [curComponent])

    return <Form
        form={form}
        onValuesChange={valuesChange}
        wrapperCol={{span: 14}}
        labelCol={{span: 8}}>
        {
            componentConfig[curComponent!.name]?.stylesSetter?.map(setter => (
                <Form.Item label={setter.label} name={setter.name} key={setter.name}>
                    {renderFormElement(setter)}
                </Form.Item>
            ))
        }
        <div className="h-[200px] border-[1px] border-[#ccc]">
            <CssEditor value={css} onChange={handleEditorChange} />
        </div>
    </Form>
}